import { Toast } from "antd-mobile";
import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  Canceler,
  InternalAxiosRequestConfig,
} from "axios";

// 用于存储请求的 CancelToken 源
const pendingRequests = new Map<string, Canceler>();

// 创建 Axios 实例
const service: AxiosInstance = axios.create({
  baseURL: process.env.REACT_APP_API_URL, // 请替换为你的 API 基础 URL
  timeout: 20000, // 请求超时时间
});

// 生成请求的唯一标识
function generateRequestKey(config: AxiosRequestConfig): string | null {
  if (!config) {
    return null;
  }
  return [
    config.method,
    config.url,
    JSON.stringify(config.params),
    JSON.stringify(config.data),
  ].join("&");
}

// 请求拦截器
service.interceptors.request.use(
  function (config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
    if (config) {
      const requestKey = generateRequestKey(config);
      // 如果有相同的请求正在进行，则取消之前的请求
      if (requestKey && pendingRequests.has(requestKey)) {
        const cancel = pendingRequests.get(requestKey)!;
        cancel("取消重复请求");
        pendingRequests.delete(requestKey);
      }
      // 为当前请求设置 CancelToken
      const source = axios.CancelToken.source();
      config.cancelToken = source.token;
      if (requestKey) {
        pendingRequests.set(requestKey, source.cancel);
      }
      // 从本地存储获取 token
      const token = localStorage.getItem("token");
      if (token) {
        // 若存在 token，添加到请求头
        config.headers = config.headers || {};
        config.headers["token"] = token;
      }
    }
    return config;
  },
  function (error: any): Promise<never> {
    // 处理请求错误
    console.error("请求错误:", error);
    return Promise.reject(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  function (response: AxiosResponse): any {
    if (response.config) {
      const requestKey = generateRequestKey(response.config);
      // 请求完成后，从 pendingRequests 中移除
      if (requestKey) {
        pendingRequests.delete(requestKey);
      }
    }

    // 处理响应数据
    const res = response.data;

    // 检查业务状态码
    if (res.code !== 200) {
      Toast.show({
        content: res?.msg || "请求失败",
      });
      // 统一错误处理
      console.error("请求失败:", res.message || "未知错误");

      // 处理特定错误码（如 1005 表示 token 失效）
      if (res.code === 1008) {
        // 清除本地存储中的 token
        localStorage.removeItem("token");
        localStorage.removeItem("info");

        // 跳转到登录页面
        window.location.href = "/"; // 或使用路由跳转，如 history.push('/')

        // 返回一个被拒绝的 Promise
        return Promise.reject(res);
      }

      // 其他错误码处理
      return Promise.reject(res);
    } else {
      // 业务状态码为 200，返回响应数据
      return response.data;
    }
  },
  function (error: any): Promise<any> {
    if (axios.isCancel(error)) {
      console.log("请求被取消:", error.message);
      // 返回一个特殊的结果，表明请求被取消
      return Promise.resolve({ canceled: true });
    } else {
      console.error("响应错误:", error);
      if (error.config) {
        const requestKey = generateRequestKey(error.config);
        // 请求出错后，从 pendingRequests 中移除
        if (requestKey) {
          pendingRequests.delete(requestKey);
        }
      }
      return Promise.reject(error);
    }
  }
);

// 封装请求方法
const request = {
  get: function (url: string, params?: any, isDownload = false): Promise<any> {
    const config: AxiosRequestConfig = {
      url,
      params,
      responseType: isDownload ? "blob" : "json", // 如果是下载请求，设置响应类型为 blob
    };
    return service.get(url, config);
  },
  post: function (url: string, data?: any, isDownload = false): Promise<any> {
    const config: AxiosRequestConfig = {
      responseType: isDownload ? "blob" : "json", // 仅设置 responseType
    };
    return service.post(url, data, config); // 正确传递 data 和 config
  },
  put: function (url: string, data?: any, isDownload = false): Promise<any> {
    const config: AxiosRequestConfig = {
      responseType: isDownload ? "blob" : "json", // 仅设置 responseType
    };
    return service.put(url, data, config); // 正确传递 data 和 config
  },
  delete: function (
    url: string,
    params?: any,
    isDownload = false
  ): Promise<any> {
    const config: AxiosRequestConfig = {
      url,
      params,
      responseType: isDownload ? "blob" : "json", // 如果是下载请求，设置响应类型为 blob
    };
    return service.delete(url, config);
  },
};

export default request;
